#ifndef GLOBALCONTEXT_H
#define GLOBALCONTEXT_H

#include <exception>
#include <WinSock2.h>
#include <Windows.h>
#include <map>
#include "CommonHdr.h"
#include "Log.h"
#include "ClientContext.h"
#include "SubstitutionList.h"

class GlobalContext
{
public:
	static GlobalContext& Instance();

	HANDLE IOCP()
	{
		return m_hIOCP;
	}

	bool AssociateHandleWithIOCP(HANDLE handle,unsigned int);

	SOCKET ListenSock()
	{
		return m_listenSock;
	}

	void SetListenSock(SOCKET sock)
	{
		this->m_listenSock=sock;
	}

	HANDLE ListenThread()
	{
		return this->m_listenThread;
	}

	void SetListenThread(HANDLE handles)
	{
		this->m_listenThread=handles;
	}

	HANDLE* WorkThreads(size_t *count)
	{
		*count=this->m_workThreadsCount;
		return this->m_workThreads;
	}

	void SetWorkThreads(HANDLE *handles,size_t count)
	{
		this->m_workThreads=handles;
		this->m_workThreadsCount=count;
	}

	DWORD WaitForAcceptEvent()
	{
		return ::WSAWaitForMultipleEvents(1,&m_hEvent,false,WSA_INFINITE,true);
	}

	int ResetEvent()
	{
		WSANETWORKEVENTS events;
		return ::WSAEnumNetworkEvents(m_listenSock,m_hEvent,&events);
	}

	std::map<unsigned int,ClientContext*>& ClientList()
	{
		return m_clients;
	}

	void SetNotifyWindow(HWND wnd)
	{
		m_notifyWnd=wnd;
	}

	HWND NotifyWindow()
	{
		return m_notifyWnd;
	}

	void EnterClientsEntryRecordLock();

	void LeaveClientsEntryRecordLock();

	void AddClient(ClientContext*);

	void RemoveClient(unsigned int);

	static void DestoryInstance();

private:
	static VOID NTAPI CancelListenProc(ULONG_PTR Parameter);

	GlobalContext();

	GlobalContext(const GlobalContext &)
	{
		throw std::exception("GlobalContext class do not allow copy operation.");
	}

	~GlobalContext();

	GlobalContext& operator=(const GlobalContext &)
	{
		throw std::exception("GlobalContext class do not allow assignment operation.");
	}

	void Dispose();

	static log4cplus::Logger log;

	static GlobalContext *m_instance;

	static unsigned int m_resourceInUse;

	static unsigned int nextRequestSequenceNo;

	HANDLE m_hIOCP;

	HANDLE m_hEvent;

	SOCKET m_listenSock;

	HANDLE m_listenThread;

	HANDLE *m_workThreads;

	size_t m_workThreadsCount;

	std::map<unsigned int,ClientContext*> m_clients;

	unsigned int m_entryRecordLock;

	HWND m_notifyWnd;
};

#endif